#include "pch.h"
#include <EventAPI.h>
#include <LoggerAPI.h>
#include <MC/Level.hpp>
#include <MC/BlockInstance.hpp>
#include <MC/Block.hpp>
#include <MC/BlockSource.hpp>
#include <MC/Actor.hpp>
#include <MC/Player.hpp>
#include <MC/ItemStack.hpp>
#include <LLAPI.h>
#include <ServerAPI.h>
#include <HookAPI.h>
#include "MkdirEx.h"
#include "TMfile.h"

Logger logger("Mine2");

inline void CheckProtocolVersion() {
    auto currentProtocol = LL::getServerProtocolVersion();
    int TARGET_BDS_PROTOCOL_VERSION = 503;
    if (TARGET_BDS_PROTOCOL_VERSION != currentProtocol)
    {
        logger.warn("Protocol version not match, target version: {}, current version: {}.",
            TARGET_BDS_PROTOCOL_VERSION, currentProtocol);
        logger.warn("This will most likely crash the server, please use the Plugin that matches the BDS version!");
    }
}

constexpr const char* CONFIG_PATH = ".\\plugins\\Mine2\\config.json";
using namespace std;
static vector<pair<string, size_t>> g_blocks;
static size_t g_weight_sum = 0;

string randomBlock() 
{
    size_t random_number = static_cast<size_t>(rand() % g_weight_sum);
    for (auto& [bloc, weight] : g_blocks) {
        if (random_number < weight) {
            return bloc;
        }
        random_number -= weight;
    }
    return "minecraft:stone";
}

THook(void, "?solidify@LiquidBlock@@IEBAXAEAVBlockSource@@AEBVBlockPos@@1@Z",
    uintptr_t _this, BlockSource* bs, BlockPos bp1, BlockPos bp2)
{
    try {
        original(_this, bs, bp1, bp2);
        auto block = bs->getBlockInstance(bp1).getBlock();
        string blockName = block->getTypeName();
        if (blockName == "minecraft:cobblestone" ||
            blockName == "minecraft:stone") 
        {
            Level::setBlock(bp1, bs->getDimensionId(), randomBlock(), 0);
        }
    }
    catch (const std::exception& e) {
        logger.error("在THook函数捕获到错误:");
        logger.error(e.what());
    }
    catch (...) {
        logger.error("在THook函数捕获到未知错误");
    }
}


void load()
{
    if (!TMfile::exists(".\\plugins\\Mine2\\config.json")) {
        nlohmann::basic_json config = {
            {"minecraft:cobblestone", 200},
            {"minecraft:coal_ore", 20},
            {"minecraft:copper_ore", 15},
            {"minecraft:iron_ore", 10},
            {"minecraft:gold_ore", 5},
            {"minecraft:emerald_ore", 3},
            {"minecraft:redstone_ore", 10},
            {"minecraft:lapis_ore", 10},
            {"minecraft:diamond_ore", 2},
        };
        TMfile::writeTo(CONFIG_PATH, config.dump(2));
        logger.warn(".\\plugins\\Mine2\\config.json was not found, it has been created automatically");
    }
    auto str = TMfile::readFrom((string)CONFIG_PATH);
    json cfg = json::parse(str);
    for (auto& [key, val] : cfg.items())
    {
        size_t st = val.get<size_t>();
        g_blocks.push_back({ key, st });
        g_weight_sum += st;
        logger.info("" + key + " : "
            + to_string(int(static_cast<double>(st * 100) / g_weight_sum))
            + '%');
    }

}

void PluginInit()
{
    try {
        CheckProtocolVersion();
        MkdirEx(".\\plugins\\Mine2");
        load();
    }
    catch (const std::exception& e) {
        logger.error("插件初始化时遇到问题:");
        logger.error(e.what());
    }
    catch (...) {
        logger.error("初始化时遇到未知问题!可能是读取过程中出错");
    }
}
